from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter
from pygments.styles import get_style_by_name
import os,sys, traceback, re


class CodeHtmlFormatter(HtmlFormatter):            
    """
    Tells traceback on what exatly line error accured    
    """
    
    def wrap(self, source, outfile):
        return self._wrap_code(source)

    def _wrap_code(self, source):                
        yield 0, '<code>'
        for i, t in source:              
            if i == 1:
                if re.match(".*?CurrentHandlingFuckingError.*?", t, re.DOTALL): 
                    t = t.replace("CurrentHandlingFuckingError",'')                        
                    t = '<div class="currentError">' + t +'</div>'                                            
            yield i, t
        yield 0, '</code>'

class watcher:    
    def __init__(self, environ):
        self.environ = environ
        

    def catch_error(self):    
        exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
        ErrorType = exceptionType.__name__ 
        currentError = traceback.format_exception(*sys.exc_info())     
        if str(ErrorType)!='SystemExit':    
            if 'HTTP_X_REQUESTED_WITH' not in self.environ:
                currentError = traceback.format_exception(*sys.exc_info())         
                errs = []
                for i in range(len(currentError)):
                    match = re.findall('File "(.+?)", line (\d{1,11})(.*?)', currentError[i],re.DOTALL)
                    if match:
                        errs.append(match)         
                errs.reverse()
                
                tabLinks = ''
                tabContent = ''
                lineContent = ''
                
                for i in range(len(errs)):
                    fileErrorPath = errs[i][0][0]
                    FError = re.findall("(\w+?\.py)", fileErrorPath,re.DOTALL)
                    if FError:
                        tabLinks += '<a>' + FError[0] + '</a>'
                    lineNumber = 1      
                    if os.path.exists(fileErrorPath):  
                        for line in open(fileErrorPath,'r').readlines():
                            if lineNumber > int(errs[i][0][1])-11 and lineNumber < int(errs[i][0][1])+13:
                               if lineNumber == int(errs[i][0][1]):                   
                                   lineContent += str(lineNumber) + '\tCurrentHandlingFuckingError'+line#+str(exceptionValue)+line
                               else:lineContent += str(lineNumber) +'\t'+ line
                            lineNumber=lineNumber+1  
                        tabContent += '<div class="Page"><pre class="syntax">'+highlight(lineContent,PythonLexer(encoding='utf-8'), CodeHtmlFormatter(encoding='utf-8'))+'</pre></div>'    
                        lineContent = ''
                #print 'Content-Type: text/html\n'
                
                return self.errorHTML(str(exceptionType.__name__),str(exceptionValue),tabLinks,tabContent,errs[0][0][0] + ' on line ' + errs[0][0][1])
                
            else:                 
                return currentError
    
    def errorHTML(self,errorType,errorMessage,tabs,errors,home_error):    
        html = """<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Python error</title></head><body>
  
           <style>
           .content {
            
            position:absolute;
            width:100%;
            top: 0;
            background-color:white;
            
            
        }
        .currentError {
            background-color: #FFEFD5;
            
            
        }
        body {
            overflow: hidden;
        }
        .errorWhere {
            padding:10px;text-align:left;font-weight:bold; margin-bottom:10px;
        }
        .s {font-family:Tahoma;font-size:12px;}
            .func {color: blue;
            font-weight:bold;
            }
            pre ins{
            margin:0px;
            padding:0px;
            color:red;
            }
            
                .Page  {
                    background-color: #F8F8F8;
                    padding: 10px;
                }
                
                .highlight {
                    margin: 5px 10px;
                }
        
                .headtitle
                {
                    color: white;
                    padding: 3px;
                    background-color: green;
                    
                    font-weight: bold;
                }
                
            pre {
            text-align:left;
                margin: 0px;
                line-height: 17px;
            }
            .TabView{
                width:100%; border:1px #CCC solid;
            }
            .TabView .Tabs {
              height:26px;display:block;
                background:#E0E0E0;
                
            }
            .TabView .Tabs a {
                display:block;float:left;padding-left:10px; padding-right:10px;line-height:24px;color:#333;text-align:center;text-decoration:none;border:1px #D6D6D6 solid;margin:0px 2px;
            }
            .TabView .Tabs a.ActiveTab{
               
                  border:1px #D6D6D6 solid;
                  background-color:Green;
                  color: White;
                  border-bottom:1px #FFF solid;
                  font-weight: bold;
            }
            .TabView .Tabs a.InactiveTab{
                
            }
            .TabView .Pages{
                width:100%;
            }
            .TabView .Pages .Page{
                height:400px;
                clear:both;
            }
            .big_err {
              text-align:left;
              font-size:13px;
              padding:10px;
              background-color:#FFEFD5;
              color:black;
              margin:10px;
              border: 1px dashed #E0E0E0;
             
              font-weight:bold;
              
            
            }
            .syntax .hll { background-color: #ffffcc }
            .syntax  { background: #f8f8f8; }
            .syntax .c { color: #408080; font-style: italic } /* Comment */
            .syntax .err { border: 1px solid #FF0000 } /* Error */
            .syntax .k { color: #008000; font-weight: bold } /* Keyword */
            .syntax .o { color: #666666 } /* Operator */
            .syntax .cm { color: #408080; font-style: italic } /* Comment.Multiline */
            .syntax .cp { color: #BC7A00 } /* Comment.Preproc */
            .syntax .c1 { color: #408080; font-style: italic } /* Comment.Single */
            .syntax .cs { color: #408080; font-style: italic } /* Comment.Special */
            .syntax .gd { color: #A00000 } /* Generic.Deleted */
            .syntax .ge { font-style: italic } /* Generic.Emph */
            .syntax .gr { color: #FF0000 } /* Generic.Error */
            .syntax .gh { color: #000080; font-weight: bold } /* Generic.Heading */
            .syntax .gi { color: #00A000 } /* Generic.Inserted */
            .syntax .go { color: #808080 } /* Generic.Output */
            .syntax .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
            .syntax .gs { font-weight: bold } /* Generic.Strong */
            .syntax .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
            .syntax .gt { color: #0040D0 } /* Generic.Traceback */
            .syntax .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
            .syntax .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
            .syntax .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
            .syntax .kp { color: #008000 } /* Keyword.Pseudo */
            .syntax .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
            .syntax .kt { color: #B00040 } /* Keyword.Type */
            .syntax .m { color: #666666 } /* Literal.Number */
            .syntax .s { color: #BA2121 } /* Literal.String */
            .syntax .na { color: #7D9029 } /* Name.Attribute */
            .syntax .nb { color: #008000 } /* Name.Builtin */
            .syntax .nc { color: #0000FF; font-weight: bold } /* Name.Class */
            .syntax .no { color: #880000 } /* Name.Constant */
            .syntax .nd { color: #AA22FF } /* Name.Decorator */
            .syntax .ni { color: #999999; font-weight: bold } /* Name.Entity */
            .syntax .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
            .syntax .nf { color: #0000FF } /* Name.Function */
            .syntax .nl { color: #A0A000 } /* Name.Label */
            .syntax .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
            .syntax .nt { color: #008000; font-weight: bold } /* Name.Tag */
            .syntax .nv { color: #19177C } /* Name.Variable */
            .syntax .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
            .syntax .w { color: #bbbbbb } /* Text.Whitespace */
            .syntax .mf { color: #666666 } /* Literal.Number.Float */
            .syntax .mh { color: #666666 } /* Literal.Number.Hex */
            .syntax .mi { color: #666666 } /* Literal.Number.Integer */
            .syntax .mo { color: #666666 } /* Literal.Number.Oct */
            .syntax .sb { color: #BA2121 } /* Literal.String.Backtick */
            .syntax .sc { color: #BA2121 } /* Literal.String.Char */
            .syntax .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
            .syntax .s2 { color: #BA2121 } /* Literal.String.Double */
            .syntax .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
            .syntax .sh { color: #BA2121 } /* Literal.String.Heredoc */
            .syntax .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
            .syntax .sx { color: #008000 } /* Literal.String.Other */
            .syntax .sr { color: #BB6688 } /* Literal.String.Regex */
            .syntax .s1 { color: #BA2121 } /* Literal.String.Single */
            .syntax .ss { color: #19177C } /* Literal.String.Symbol */
            .syntax .bp { color: #008000 } /* Name.Builtin.Pseudo */
            .syntax .vc { color: #19177C } /* Name.Variable.Class */
            .syntax .vg { color: #19177C } /* Name.Variable.Global */
            .syntax .vi { color: #19177C } /* Name.Variable.Instance */
            .syntax .il { color: #666666 } /* Literal.Number.Integer.Long */
            .tab {
                padding:3px; background-color:#F2F2F2; border:1px solid #E1E1E1; padding-left:10px; padding-right:10px; color:gray;    
                cursor:pointer;
            }
           </style>
           <div class="content" align=center><div class="s" style="width:90%;">
            <div class="headtitle" align=left>"""+home_error+"""</div>
            </div><div class="s" style="width:90%;border:1px solid #F0F0F0;">
           <!-- <div class="errorWhere" >"""+home_error+"""</div> -->
            
            <div class="big_err">"""+errorType+""": """+errorMessage+"""</div>
           
           <div class="TabView" id="TabView1">
            
            <div class="Tabs">"""+tabs+"""</div>
           
            <div class="Pages">
                
              """+errors+"""
                
            </div>
        </div>
        <script type="text/javascript">
        function TabView(id, current){
            if(typeof(TabView.cnt) == "undefined"){
                TabView.init();
            }
            current = (typeof(current) == "undefined") ? 0 : current;
            this.newTab(id, current);
        }
        TabView.init = function(){
            TabView.cnt = 0;
            TabView.arTabView = new Array();
        }
        TabView.switchTab = function(TabViewIdx, TabIdx){
            TabView.arTabView[TabViewIdx].TabView.switchTab(TabIdx);
        }
        TabView.prototype.newTab = function(id, current){
            var TabViewElem, idx = 0, el = '', elTabs = '', elPages = '';
            TabViewElem = document.getElementById(id);
            TabView.arTabView[TabView.cnt] = TabViewElem;
            this.TabElem = TabViewElem;
            this.TabElem.TabView = this;
            this.tabCnt = 0;
            this.arTab = new Array();
            // Loop throught the elements till the object with
            // classname 'Tabs' is obtained
            elTabs = TabViewElem.firstChild;
            while(elTabs.className != "Tabs" )elTabs = elTabs.nextSibling;
            el = elTabs.firstChild;
            do{
                if(el.tagName == "A"){
                    el.href = "javascript:TabView.switchTab(" + TabView.cnt + "," + idx + ");";
                    this.arTab[idx] = new Array(el, 0);
                    this.tabCnt = idx++;
                }
            }while (el = el.nextSibling);
        
            // Loop throught the elements till the object with
            // classname 'Pages' is obtained
            elPages = TabViewElem.firstChild;
            while (elPages.className != "Pages")elPages = elPages.nextSibling;
            el = elPages.firstChild;
            idx = 0;
            do{
                if(el.className == "Page"){
                    this.arTab[idx][1] = el;
                    idx++;
                }
            }while (el = el.nextSibling);
            this.switchTab(current);
            // Update TabView Count
            TabView.cnt++;
        }
        TabView.prototype.switchTab = function(TabIdx){
            var Tab;
            if(this.TabIdx == TabIdx)return false;
            for(idx in this.arTab){
                Tab = this.arTab[idx];
                if(idx == TabIdx){
                    Tab[0].className = "ActiveTab";
                    Tab[1].style.display = "block";
                    Tab[0].blur();
                }else{
                    Tab[0].className = "InactiveTab";
                    Tab[1].style.display = "none";
                }
            }
            this.TabIdx = TabIdx;
           
        }
        
            t1 = new TabView('TabView1');  
            </script>
            </div></div></div></body></html>
    
        """
        return html
    
            
            
            
            